#include <sys/epoll.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <iostream>
#include <cstring>

const int MAX_EVENTS = 10;
const char* SERVER_IP = "127.0.0.1";
const int PORT = 8888;

// 设置非阻塞模式‌:ml-citation{ref="7" data="citationList"}
void setNonblocking(int fd) {
    int flags = fcntl(fd, F_GETFL, 0);
    fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}

int main() {
    // 1. 创建epoll实例‌:ml-citation{ref="2,6" data="citationList"}
    int epollFd = epoll_create1(0);
    epoll_event events[MAX_EVENTS];

    // 2. 创建连接Socket‌:ml-citation{ref="4,7" data="citationList"}
    int sockFd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
    setNonblocking(sockFd);

    sockaddr_in servAddr{AF_INET, htons(PORT)};
    inet_pton(AF_INET, SERVER_IP, &servAddr.sin_addr);

    // 3. 发起异步连接‌:ml-citation{ref="7" data="citationList"}
    int ret = connect(sockFd, (sockaddr*)&servAddr, sizeof(servAddr));
    if(ret == -1 && errno != EINPROGRESS) {
        perror("connect error");
        return EXIT_FAILURE;
    }

    // 4. 注册EPOLLOUT事件监听连接结果‌:ml-citation{ref="7" data="citationList"}
    epoll_event ev{.events = EPOLLOUT | EPOLLET, .data = {.fd = sockFd}};
    epoll_ctl(epollFd, EPOLL_CTL_ADD, sockFd, &ev);

    // 5. 事件循环处理‌:ml-citation{ref="6,7" data="citationList"}
    bool connected = false;
    while(true) {
        int ready = epoll_wait(epollFd, events, MAX_EVENTS, -1);
        for(int i=0; i<ready; ++i) {
            int fd = events[i].data.fd;
            
            // 处理连接结果‌:ml-citation{ref="7" data="citationList"}
            if(events[i].events & EPOLLOUT) {
                int error = 0;
                socklen_t len = sizeof(error);
                getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len);
                
                if(error == 0) {
                    connected = true;
                    std::cout << "Connected to server!" << std::endl;
                    // 修改为监听读事件
                    ev.events = EPOLLIN | EPOLLET;
                    epoll_ctl(epollFd, EPOLL_CTL_MOD, fd, &ev);
                    // 发送测试数据
                    const char* msg = "Hello Server!";
                    send(fd, msg, strlen(msg), 0);
                } else {
                    perror("connection failed");
                    close(fd);
                    return EXIT_FAILURE;
                }
            }
            
            // 处理接收数据‌:ml-citation{ref="7" data="citationList"}
            if(connected && (events[i].events & EPOLLIN)) {
                char buffer[1024];
                ssize_t n;
                while((n = recv(fd, buffer, sizeof(buffer)-1, 0)) > 0) {
                    buffer[n] = '\0';
                    std::cout << "Received: " << buffer << std::endl;
                }
                if(n == 0 || (n == -1 && errno != EAGAIN)) {
                    std::cout << "Connection closed" << std::endl;
                    close(fd);
                    return EXIT_SUCCESS;
                }
            }
        }
    }

    // 清理资源‌:ml-citation{ref="2" data="citationList"}
    close(sockFd);
    close(epollFd);
    return 0;
}
